package com.njtoyo.taxi.admin.logic.data;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njtoyo.taxi.admin.mapper.secondary.entity.cache.CacheDriverPhoneCallRideCount;
import com.njtoyo.taxi.admin.mapper.secondary.entity.cache.CacheDriverRidePickCount;
import com.njtoyo.taxi.admin.mapper.secondary.entity.cache.CacheDriverScanRideCount;
import com.njtoyo.taxi.admin.mapper.secondary.entity.cache.CacheDriverSimpleCallRideCount;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardOrderDaily;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardOrderMinute;
import com.njtoyo.taxi.admin.mapper.secondary.enums.DataOrderType;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.cache.CacheDriverPhoneCallRideCountMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.cache.CacheDriverRidePickCountMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.cache.CacheDriverScanRideCountMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.cache.CacheDriverSimpleCallRideCountMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.data.DashboardOrderDailyMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.data.DashboardOrderMinuteMapper;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.RankListRankTotalPresenter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class DashboardOrderLogic {
    @Autowired
    private DashboardOrderDailyMapper dashboardOrderDailyMapper;

    @Autowired
    private DashboardOrderMinuteMapper dashboardOrderMinuteMapper;

    @Autowired
    private CacheDriverRidePickCountMapper cacheDriverRidePickCountMapper;

    @Autowired
    private CacheDriverScanRideCountMapper cacheDriverScanRideCountMapper;

    @Autowired
    private CacheDriverPhoneCallRideCountMapper cacheDriverPhoneCallRideCountMapper;

    @Autowired
    private CacheDriverSimpleCallRideCountMapper cacheDriverSimpleCallRideCountMapper;

    // 按照【区域】分组，根据时间范围从dashboard_order_daily中获取接单量
    public List<DashboardOrderDaily> getRidePickCountFromDailyGroupByCanton(List<Long> isImitates, Date startTime, Date endTime) {
        String start = DateUtil.formatDate(startTime);
        String end = DateUtil.formatDate(endTime);

        QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, canton_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.isNotNull("canton_id");
        queryWrapper.groupBy("canton_id");

        return dashboardOrderDailyMapper.selectList(queryWrapper);
    }

    // 按照【区域】分组，根据时间范围从dashboard_order_minute中获取接单量
    public List<DashboardOrderMinute> getRidePickCountFromMinuteGroupByCanton(List<Long> isImitates, Date startTime, Date endTime) {
        String start = DateUtil.formatDateTime(startTime);
        String end = DateUtil.formatDateTime(endTime);

        QueryWrapper<DashboardOrderMinute> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, canton_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.isNotNull("canton_id");
        queryWrapper.groupBy("canton_id");

        return dashboardOrderMinuteMapper.selectList(queryWrapper);
    }

    // 按照【区域】分组，根据时间范围从dashboard_order_daily中获取接单量
    public List<DashboardOrderDaily> getNoResponseCallCountFromDailyGroupByCanton(List<Long> isImitates, Date startTime, Date endTime) {
        String start = DateUtil.formatDate(startTime);
        String end = DateUtil.formatDate(endTime);

        QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, canton_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.noResponseAppointment, DataOrderType.noResponseReal);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.isNotNull("canton_id");
        queryWrapper.groupBy("canton_id");

        return dashboardOrderDailyMapper.selectList(queryWrapper);
    }

    // 按照【区域】分组，根据时间范围从dashboard_order_minute中获取接单量
    public List<DashboardOrderMinute> getNoResponseCallCountFromMinuteGroupByCanton(List<Long> isImitates, Date startTime, Date endTime) {
        String start = DateUtil.formatDateTime(startTime);
        String end = DateUtil.formatDateTime(endTime);

        QueryWrapper<DashboardOrderMinute> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, canton_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.noResponseAppointment, DataOrderType.noResponseReal);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.isNotNull("canton_id");
        queryWrapper.groupBy("canton_id");

        return dashboardOrderMinuteMapper.selectList(queryWrapper);
    }

    // 按照【公司id】分组，根据时间范围从dashboard_order_daily中获取接单量
    public List<DashboardOrderDaily> getRidePickCountFromDailyGroupByCompany(List<Long> isImitates, Date startTime, Date endTime, List<Long> companyIds) {
        String start = DateUtil.formatDate(startTime);
        String end = DateUtil.formatDate(endTime);

        QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, company_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.in("company_id", companyIds);
        queryWrapper.groupBy("company_id");

        return dashboardOrderDailyMapper.selectList(queryWrapper);
    }

    // 按照【公司id】分组，根据时间范围从dashboard_order_minute中获取接单量
    public List<DashboardOrderMinute> getRidePickCountFromMinuteGroupByCompany(List<Long> isImitates, Date startTime, Date endTime, List<Long> companyIds) {
        String start = DateUtil.formatDateTime(startTime);
        String end = DateUtil.formatDateTime(endTime);

        QueryWrapper<DashboardOrderMinute> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(SUM(num), 0) as total, company_id");
        queryWrapper.in("is_imitate", isImitates);
        queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.in("company_id", companyIds);
        queryWrapper.groupBy("company_id");

        return dashboardOrderMinuteMapper.selectList(queryWrapper);
    }

    // 按照【司机id】分组，根据时间范围从cache_driver_ride_pick_count+cache_driver_scan_ride_count中获取接单量
    public List<RankListRankTotalPresenter> getRidePickCountGroupByDriver(Date startTime, Date endTime, List<Long> driverIds) {
        String startTimeStr = DateUtil.formatDate(startTime);
        String endTimeStr = DateUtil.formatDate(endTime);

        // cache_driver_ride_pick_count
        QueryWrapper<CacheDriverRidePickCount> cacheDriverRidePickCountQueryWrapper = new QueryWrapper<>();

        // cache_driver_scan_ride_count
        QueryWrapper<CacheDriverScanRideCount> cacheDriverScanRideCountQueryWrapper = new QueryWrapper<>();

        // cache_driver_phone_call_ride_count
        QueryWrapper<CacheDriverPhoneCallRideCount> cacheDriverPhoneCallRideCountQueryWrapper = new QueryWrapper<>();

        // cache_driver_simple_call_ride_count
        QueryWrapper<CacheDriverSimpleCallRideCount> cacheDriverSimpleCallRideCountQueryWrapper = new QueryWrapper<>();

        List<RankListRankTotalPresenter> totalPresenter = new ArrayList<>();

        // ride
        cacheDriverRidePickCountQueryWrapper.select("IFNULL(SUM(`value`), 0) as total, driver_id");
        cacheDriverRidePickCountQueryWrapper.between("DATE_FORMAT(CONCAT_WS('-', `year`, `month`, `day`), '%Y-%m-%d')", startTimeStr, endTimeStr);
        cacheDriverRidePickCountQueryWrapper.in("driver_id", driverIds);
        cacheDriverRidePickCountQueryWrapper.groupBy("driver_id");

        List<CacheDriverRidePickCount> driverRidePickCounts = cacheDriverRidePickCountMapper.selectList(cacheDriverRidePickCountQueryWrapper);

        // scan
        cacheDriverScanRideCountQueryWrapper.select("IFNULL(SUM(`value`), 0) as total, driver_id");
        cacheDriverScanRideCountQueryWrapper.between("DATE_FORMAT(CONCAT_WS('-', `year`, `month`, `day`), '%Y-%m-%d')", startTimeStr, endTimeStr);
        cacheDriverScanRideCountQueryWrapper.in("driver_id", driverIds);
        cacheDriverScanRideCountQueryWrapper.groupBy("driver_id");

        List<CacheDriverScanRideCount> driverScanRideCounts = cacheDriverScanRideCountMapper.selectList(cacheDriverScanRideCountQueryWrapper);

        // phone_call
        cacheDriverPhoneCallRideCountQueryWrapper.select("IFNULL(SUM(`value`), 0) as total, driver_id");
        cacheDriverPhoneCallRideCountQueryWrapper.between("DATE_FORMAT(CONCAT_WS('-', `year`, `month`, `day`), '%Y-%m-%d')", startTimeStr, endTimeStr);
        cacheDriverPhoneCallRideCountQueryWrapper.in("driver_id", driverIds);
        cacheDriverPhoneCallRideCountQueryWrapper.groupBy("driver_id");

        List<CacheDriverPhoneCallRideCount> driverPhoneCallCounts = cacheDriverPhoneCallRideCountMapper.selectList(cacheDriverPhoneCallRideCountQueryWrapper);

        // simple_call
        cacheDriverSimpleCallRideCountQueryWrapper.select("IFNULL(SUM(`value`), 0) as total, driver_id");
        cacheDriverSimpleCallRideCountQueryWrapper.between("DATE_FORMAT(CONCAT_WS('-', `year`, `month`, `day`), '%Y-%m-%d')", startTimeStr, endTimeStr);
        cacheDriverSimpleCallRideCountQueryWrapper.in("driver_id", driverIds);
        cacheDriverSimpleCallRideCountQueryWrapper.groupBy("driver_id");

        List<CacheDriverSimpleCallRideCount> driverSimpleCallCounts = cacheDriverSimpleCallRideCountMapper.selectList(cacheDriverSimpleCallRideCountQueryWrapper);

        // ride
        driverRidePickCounts.forEach(i -> {
            RankListRankTotalPresenter rank = new RankListRankTotalPresenter();
            rank.setDriverId(i.getDriverId());
            rank.setTotalNumber(i.getTotal());

            totalPresenter.add(rank);
        });

        // scan
        driverScanRideCounts.forEach(i -> {
            RankListRankTotalPresenter rank = new RankListRankTotalPresenter();
            rank.setDriverId(i.getDriverId());
            rank.setTotalNumber(i.getTotal());

            totalPresenter.add(rank);
        });

        // phone_call
        driverPhoneCallCounts.forEach(i -> {
            RankListRankTotalPresenter rank = new RankListRankTotalPresenter();
            rank.setDriverId(i.getDriverId());
            rank.setTotalNumber(i.getTotal());

            totalPresenter.add(rank);
        });

        // simple_call
        driverSimpleCallCounts.forEach(i -> {
            RankListRankTotalPresenter rank = new RankListRankTotalPresenter();
            rank.setDriverId(i.getDriverId());
            rank.setTotalNumber(i.getTotal());

            totalPresenter.add(rank);
        });

        List<RankListRankTotalPresenter> returnPresenter = new ArrayList<>();

        Map<Long, LongSummaryStatistics> convert =
                totalPresenter.stream().filter(item -> Objects.nonNull(item.getDriverId()))
                        .collect(Collectors.groupingBy(RankListRankTotalPresenter::getDriverId, Collectors.summarizingLong(RankListRankTotalPresenter::getTotalNumber)));

        for (Map.Entry<Long, LongSummaryStatistics> entry : convert.entrySet()) {
            LongSummaryStatistics longSummaryStatistics = entry.getValue();

            RankListRankTotalPresenter item = new RankListRankTotalPresenter();
            item.setDriverId(entry.getKey());
            item.setTotalNumber(longSummaryStatistics.getSum());

            returnPresenter.add(item);
        }

        return returnPresenter;
    }
}
